/*
 *
 *      Copyright (c) 2018-2025, lengleng All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the pig4cloud.com developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: lengleng (wangiegie@gmail.com)
 *
 */

package com.pig4cloud.pig.admin.controller;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.pig4cloud.pig.admin.api.dto.SysUserInfo;
import com.pig4cloud.pig.admin.api.dto.UserDTO;
import com.pig4cloud.pig.admin.api.entity.SysDept;
import com.pig4cloud.pig.admin.api.entity.SysDeptGroup;
import com.pig4cloud.pig.admin.api.entity.SysUser;
import com.pig4cloud.pig.admin.api.entity.SysUserTenant;
import com.pig4cloud.pig.admin.api.vo.UserSelectVO;
import com.pig4cloud.pig.admin.api.vo.UserVO;
import com.pig4cloud.pig.admin.config.AdminProperties;
import com.pig4cloud.pig.admin.service.SysDeptGroupService;
import com.pig4cloud.pig.admin.service.SysDeptService;
import com.pig4cloud.pig.admin.service.SysUserService;
import com.pig4cloud.pig.admin.service.SysUserTenantService;
import com.pig4cloud.pig.common.core.constant.CommonConstants;
import com.pig4cloud.pig.common.core.util.R;
import com.pig4cloud.pig.common.log.annotation.SysLog;
import com.pig4cloud.pig.common.security.annotation.Inner;
import com.pig4cloud.pig.common.security.tenant.TenantContextHolder;
import com.pig4cloud.pig.common.security.util.SecurityUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author lengleng
 * @date 2018/12/16
 */
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping({"/user", "/cpsRole/user"})
@Api(value = "user", tags = "用户管理模块")
public class SysUserController {
	private final SysUserService userService;
	private final SysUserTenantService sysUserTenantService;
	private final SysDeptGroupService sysDeptGroupService;
	private final SysDeptService sysDeptService;
	private final AdminProperties adminProperties;

	/**
	 * 获取当前用户全部信息
	 *
	 * @return 用户信息
	 */
	@GetMapping(value = {"/info"})
	public R info() {
		String username = SecurityUtils.getUser().getUsername();
		SysUser user = userService.getOne(Wrappers.<SysUser>query()
				.lambda().eq(SysUser::getUsername, username));
		if (user == null) {
			return R.failed(null, "获取当前用户信息失败");
		}
		return R.ok(userService.findUserInfo(user));
	}

	/**
	 * 获取指定用户全部信息
	 *
	 * @return 用户信息
	 */
	@Inner
	@GetMapping("/info/{username}")
	public R info(@PathVariable String username) {
		SysUser user = userService.getOne(Wrappers.<SysUser>query()
				.lambda().eq(SysUser::getUsername, username));
		if (user == null) {
			return R.failed(null, String.format("用户信息为空 %s", username));
		}
		return R.ok(userService.findUserInfo(user));
	}

	@GetMapping("/findUserByUserId/{userId}")
	@Inner
	public R findUserByUserId(@PathVariable("userId") Integer userId) {
		SysUser user = userService.getOne(Wrappers.<SysUser>query()
				.lambda().eq(SysUser::getUserId, userId));
		if (user == null) {
			return R.failed(null, String.format("用户信息为空 %s", userId));
		}
		return R.ok(userService.findUserInfo(user));
	}

	/**
	 * 通过ID查询用户信息
	 *
	 * @param id ID
	 * @return 用户信息
	 */
	@GetMapping("/{id}")
	public R user(@PathVariable Integer id) {
		return R.ok(userService.selectUserVoById(id));
	}

	/**
	 * 根据用户名查询用户信息
	 *
	 * @param username 用户名
	 * @return
	 */
	@GetMapping("/details/{username}")
	public R user(@PathVariable String username) {
		SysUser condition = new SysUser();
		condition.setUsername(username);
		SysUser sysUser = userService.getOne(new QueryWrapper<>(condition));
		//新增用户校验用户名在调用
		if (sysUser != null) {
			sysUser.setTenantId(SecurityUtils.getTenantId());
			//设置部门ID、组别ID、租户ID、租户状态
			SysUserTenant userTenant = sysUserTenantService.getOne(Wrappers.<SysUserTenant>lambdaQuery()
					.eq(SysUserTenant::getTenantId, SecurityUtils.getTenantId())
					.eq(SysUserTenant::getUserId, sysUser.getUserId()));
			if (userTenant != null) {
				sysUser.setDeptId(userTenant.getDeptId());
				sysUser.setDeptGroupId(userTenant.getDeptGroupId());
				sysUser.setStatus(userTenant.getStatus());
			} else {
				//初始化租户后，不绑定租户直接编辑用户的情况
				sysUser.setDeptId(null);
				sysUser.setDeptGroupId(null);
				sysUser.setStatus(0);
			}
		}
		return R.ok(sysUser);
	}

	/**
	 * 删除用户信息
	 *
	 * @param id ID
	 * @return R
	 */
	@SysLog("删除用户信息")
	@DeleteMapping("/{id}")
	@PreAuthorize("@pms.hasPermission('sys_user_del*')")
	@ApiOperation(value = "删除用户", notes = "根据ID删除用户")
	@ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "int", paramType = "path")
	public R userDel(@PathVariable Integer id) {
		SysUser sysUser = userService.getById(id);
		return R.ok(userService.deleteUserById(sysUser));
	}

	/**
	 * 添加用户
	 *
	 * @param userDto 用户信息
	 * @return success/false
	 */
	@SysLog("添加用户")
	@PostMapping
	@PreAuthorize("@pms.hasPermission('sys_user_add*')")
	public R user(@RequestBody UserDTO userDto) {
		return R.ok(userService.saveUser(userDto));
	}

	/**
	 * 更新用户信息
	 *
	 * @param userDto 用户信息
	 * @return R
	 */
	@SysLog("更新用户信息")
	@PutMapping
	@PreAuthorize("@pms.hasPermission('sys_user_edit*')")
	public R updateUser(@Valid @RequestBody UserDTO userDto) {
		if (Objects.isNull(userDto.getDeptId()) || 0 == userDto.getDeptId()) {
			return R.failed("请选择部门");
		}
		return R.ok(userService.updateUser(userDto));
	}

	/**
	 * 分页查询用户
	 *
	 * @param page    参数集
	 * @param userDTO 查询参数列表
	 * @return 用户集合
	 */
	@GetMapping("/page")
	public R getUserPage(Page page, UserDTO userDTO) {
		return R.ok(userService.getCpsOrNonCusUserVosPage(page, userDTO));
	}

	/**
	 * 修改个人信息
	 *
	 * @param userDto userDto
	 * @return success/false
	 */
	@SysLog("修改个人信息")
	@PutMapping("/edit")
	public R updateUserInfo(@Valid @RequestBody UserDTO userDto) {
		return userService.updateUserInfo(userDto);
	}

	/**
	 * @param username 用户名称
	 * @return 上级部门用户列表
	 */
	@GetMapping("/ancestor/{username}")
	public R listAncestorUsers(@PathVariable String username) {
		return R.ok(userService.listAncestorUsers(username));
	}


	/**
	 * 所有用户信息
	 *
	 * @return
	 */
	@Inner
	@RequestMapping("/getUserList")
	public R userList() {
		//设置where条件
		QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
		//queryWrapper.eq("del_flag",0);
		List<SysUser> userList = userService.list(queryWrapper);
		if (org.apache.commons.collections.CollectionUtils.isNotEmpty(userList)){
			Integer tenantId = SecurityUtils.getTenantId();
			List<SysUserTenant> sysUserTenantList = sysUserTenantService.list(Wrappers.<SysUserTenant>lambdaQuery().eq(SysUserTenant::getTenantId,tenantId).eq(SysUserTenant::getStatus, 1));
			for (SysUser sysUser : userList) {
				List<SysUserTenant> sysUserTenantListFilter = sysUserTenantList.stream().filter(item -> item.getUserId().equals(sysUser.getUserId())).collect(Collectors.toList());
				if (org.apache.commons.collections.CollectionUtils.isNotEmpty(sysUserTenantListFilter)){
					sysUser.setStatus(1);
				}
			}
		}
		return R.ok(userList);
	}


	/**
	 * 所有用户信息（下拉列表）-- 不带（已删除的用户，项目未激活或账号已锁定）
	 *
	 * @return
	 */
	@RequestMapping("/getUserSelectList")
	public R userSelectList() {
		List<SysUser> userList = userService.list();
		List<UserSelectVO> list = new ArrayList<>();
		if (userList != null && userList.size() > 0) {
			for (SysUser sysUser : userList) {
				UserSelectVO userSelectVO = new UserSelectVO();
				BeanUtils.copyProperties(sysUser, userSelectVO);
				list.add(userSelectVO);
			}
		}
		return R.ok(list);
	}

	/**
	 * 所有用户信息（下拉列表）-- 不带（已删除的用户，项目未激活或账号已锁定）
	 *
	 * @return
	 */
	@RequestMapping("/getCpsUserSelectList")
	public R cpsUserSelectList() {
		//查询当前租户
		return R.ok(userService.getUserSelectList());
	}

	/**
	 * 所有用户信息（下拉列表）-- 带已删除的用户
	 *
	 * @return
	 */
	@RequestMapping("/getUserSelectList4All")
	public R userSelectList4All() {
		List<UserVO> userList = userService.getUserSelectList4All();
		List<UserSelectVO> list = new ArrayList<>();
		if (userList != null && userList.size() > 0) {
			for (UserVO sysUser : userList) {
				UserSelectVO userSelectVO = new UserSelectVO();
				BeanUtils.copyProperties(sysUser, userSelectVO);
				list.add(userSelectVO);
			}
		}
		return R.ok(list);
	}

	/**
	 * 所有用户信息
	 *
	 * @return
	 */
	@Inner
	@RequestMapping("/getUserListByUserIds")
	public R getUserListByUserIds(@RequestBody List<Integer> ids) {
		LambdaQueryWrapper<SysUser> query = new LambdaQueryWrapper<>();
		query.and(CollectionUtils.isNotEmpty(ids), wrapper -> wrapper.in(SysUser::getUserId, ids));
		List<SysUser> userList = userService.list(query);
		return R.ok(userList);
	}

	@Inner
	@RequestMapping("/getDeptIdByIds")
	public R getDeptIdByIds(@RequestBody List<Integer> userIds) {
		List<Integer> resultList = new ArrayList<>();
		Integer tenantId = SecurityUtils.getTenantId();
		List<SysUserTenant> sysUserTenantList = sysUserTenantService.list(Wrappers.<SysUserTenant>lambdaQuery()
				.in(SysUserTenant::getUserId, userIds)
				.eq(SysUserTenant::getTenantId, tenantId));
		List<Integer> deptIds = sysUserTenantList.stream().filter(Objects::nonNull).map(SysUserTenant::getDeptId).distinct().collect(Collectors.toList());
		resultList = getPid(resultList, deptIds);
		log.error("resultList==" + JSON.toJSONString(resultList));
		return R.ok(resultList);
	}

	private List<Integer> getPid(List<Integer> resultList, List<Integer> deptIds) {
		resultList.addAll(deptIds);
		List<SysDept> deptList = sysDeptService.list(Wrappers.<SysDept>lambdaQuery().in(SysDept::getDeptId, deptIds));
		List<Integer> pIds = deptList.stream().filter(item -> item.getParentId() != 0).map(SysDept::getParentId).distinct().collect(Collectors.toList());
		if (CollectionUtils.isNotEmpty(pIds)) {
			getPid(resultList, pIds);
		}
		return resultList;
	}

	@Inner
	@RequestMapping("/getUserInfoByIds")
	public R getUserInfoByIds(@RequestBody List<Integer> ids) {
		LambdaQueryWrapper<SysUser> query = new LambdaQueryWrapper<>();
		query.and(CollectionUtils.isNotEmpty(ids), wrapper -> wrapper.in(SysUser::getUserId, ids));
		List<SysUser> userList = userService.list(query);
		Integer tenantId = SecurityUtils.getTenantId();
		Map<Integer, String> userMap = userList.stream().collect(Collectors.toMap(SysUser::getUserId, SysUser::getRealName));
		List<Integer> userIds = userList.stream().map(SysUser::getUserId).collect(Collectors.toList());

		List<SysUserTenant> sysUserTenantList = sysUserTenantService.list(Wrappers.<SysUserTenant>lambdaQuery()
				.in(SysUserTenant::getUserId, userIds)
				.eq(SysUserTenant::getTenantId, tenantId));


		List<SysUserInfo> result = Lists.newArrayList();
		if (CollectionUtils.isNotEmpty(sysUserTenantList)) {
			//去重获取组别ID和部门ID
			List<Integer> deptIds = sysUserTenantList.stream().filter(Objects::nonNull).distinct().map(SysUserTenant::getDeptId).collect(Collectors.toList());
			List<Integer> deptGroupIds = sysUserTenantList.stream().filter(Objects::nonNull).distinct().map(SysUserTenant::getDeptGroupId).collect(Collectors.toList());
			List<SysDept> deptList = sysDeptService.list(Wrappers.<SysDept>lambdaQuery().in(SysDept::getDeptId, deptIds));
			List<SysDeptGroup> deptGroupList = sysDeptGroupService.list(Wrappers.<SysDeptGroup>lambdaQuery().in(SysDeptGroup::getId, deptGroupIds));
			Map<Integer, String> deptMap = deptList.stream().collect(Collectors.toMap(SysDept::getDeptId, SysDept::getName));
			Map<Integer, String> deptGroupMap = deptGroupList.stream().collect(Collectors.toMap(SysDeptGroup::getId, SysDeptGroup::getName));

			//Map<Integer,SysUserTenant> userTenantMap = sysUserTenantList.stream().collect(Collectors.toMap(SysUserTenant::getUserId, Function.identity()));
			sysUserTenantList.forEach(userInfo -> {
				SysUserInfo sysUserInfo = new SysUserInfo();
				sysUserInfo.setUserId(userInfo.getUserId());
				sysUserInfo.setDeptId(userInfo.getDeptId());
				sysUserInfo.setDeptGroupId(userInfo.getDeptGroupId());
				sysUserInfo.setUserName(userMap.get(userInfo.getUserId()));
				sysUserInfo.setDeptName(deptMap.get(userInfo.getDeptId()));
				sysUserInfo.setDeptGroupName(deptGroupMap.get(userInfo.getDeptGroupId()));

				result.add(sysUserInfo);
			});
		}
		return R.ok(result);
	}

	@Inner
	@RequestMapping("/getUserListByGroupId")
	public R getUserListByGroupId(@RequestBody Integer deptGroupId) {
		Integer tenantId = SecurityUtils.getTenantId();
		List<SysUserTenant> sysUserTenantList = sysUserTenantService.list(Wrappers.<SysUserTenant>lambdaQuery()
				.eq(SysUserTenant::getDeptGroupId, deptGroupId)
				.eq(SysUserTenant::getTenantId, tenantId));
		return R.ok(sysUserTenantList);
	}


	@Inner
	@RequestMapping("/getUserListByGroupIdAndTId")
	public R getUserListByGroupId(@RequestParam Integer deptGroupId,
								  @RequestParam Integer tenantId) {
		List<SysUserTenant> sysUserTenantList = sysUserTenantService.list(Wrappers.<SysUserTenant>lambdaQuery()
				.eq(SysUserTenant::getDeptGroupId, deptGroupId)
				.eq(SysUserTenant::getTenantId, tenantId));
		return R.ok(sysUserTenantList);
	}

	/**
	 * 根据用户ID列表获取用户姓名
	 *
	 * @param userIds
	 * @return
	 */
	@Inner
	@RequestMapping("/getUserIdAndNameByIds")
	public R<List<SysUser>> getUserIdAndNameByIds(@RequestBody List<Integer> userIds) {
		final List<SysUser> userList = userService.getUserIdAndNameByIds(userIds);
		return R.ok(userList);
	}

	@Inner(value = false)
	@RequestMapping("/getUserSelectListByTenantId")
	public R<List<SysUser>> getUserSelectListByTenantId(@RequestParam Integer tenantId) {
		List<SysUser> result = new ArrayList<>();
		final List<SysUserTenant> sysUserTenantList = sysUserTenantService.list(Wrappers.<SysUserTenant>lambdaQuery()
				.eq(SysUserTenant::getTenantId, tenantId).eq(SysUserTenant::getStatus,1));
		if (CollectionUtils.isNotEmpty(sysUserTenantList)){
			List<Integer> userIds = sysUserTenantList.stream().map(sysUserTenant -> sysUserTenant.getUserId()).collect(Collectors.toList());
			List<SysUser> userList = userService.getUserIdAndNameByList(userIds);
			result.addAll(userList);
		}
		return R.ok(result);
	}

}
